package com.bg.rpc.proxy;

import com.bg.rpc.client.RPCClient;
import com.bg.rpc.constant.Constant;
import com.bg.rpc.protocol.RPCRequest;
import com.bg.rpc.protocol.RPCResponse;
import com.bg.rpc.zk.ServiceDiscovery;
import lombok.Data;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.UUID;

/**
 * @Auther: zhengshunzhi
 * @Date: 2018/8/24 22:36
 * @Description: 代理类
 */
@Data
public class RPCProxy {
    private String serverAddress;
    private ServiceDiscovery serviceDiscovery;

    public RPCProxy(ServiceDiscovery serviceDiscovery) {
        this.serviceDiscovery = serviceDiscovery;
    }

    /**
     * 功能描述: 对需要提供服务的类进行代理
     * @param: interfaceClass
     * @return: T
     * @auther: bonree
     * @date: 2018/8/28 17:38
     */
    public <T> T create(Class<?> interfaceClass) {
        return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[] { interfaceClass },
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        RPCRequest request = new RPCRequest(); // 创建并初始化 RPC 请求
                        //创建请求id
                        request.setRequestId(UUID.randomUUID().toString());
                        //获取这个类的名称
                        request.setClassName(method.getDeclaringClass().getName());
                        //获取这个类方法的名称
                        request.setMethodName(method.getName());
                        //获取参数类型
                        request.setParameterTypes(method.getParameterTypes());
                        //获取参数
                        request.setParameters(args);

                        if (serviceDiscovery != null) {
                            serverAddress = serviceDiscovery.discover(); // 发现服务
                        }
                        String[] array = serverAddress.split(Constant.ZK_IP_SPLIT);
                        String host = array[0];
                        int port = Integer.parseInt(array[1]);

                        RPCClient client = new RPCClient(host, port); // 初始化 RPC
                        // 客户端
                        RPCResponse response = client.send(request); // 通过 RPC
                        if (response.getError() != null) {
                            throw response.getError();
                        } else {
                            return response.getResult();
                        }
                    }
                });
    }
}
